Casbin 的 RBAC 模型
RBAC 模型
ACL 模型在用户和资源都比较少的情况下没什么问题,但是用户和资源量一大,ACL 就会变得异常繁琐。想象一下,每次新增一个用户,都要把他需要的权限重新设置一遍是多么地痛苦。
RBAC(role-based-access-control)模型通过引入角色(role)这个中间层来解决这个问题。每个用户都属于一个角色,例如开发者、管理员、运维等,每个角色都有其特定的权限,权限的增加和删除都通过角色来进行。
这样新增一个用户时,我们只需要给他指派一个角色,他就能拥有该角色的所有权限。修改角色的权限时,属于这个角色的用户权限就会相应的修改。
RBAC 是什么?
RBAC就是一个权限控制模型,这个模型是经过时间沉淀之后,相当通用、成熟且被大众接受认可的一个模型。
RBAC 是 Role Based Access Control 的缩写,是基于角色的访问控制。
一般都是分为
- 用户(user)
- 角色(role)
- 权限(permission)
三个实体,角色(role)和权限(permission)是多对多的关系,用户(user)和角色(role)也是多对多的关系。
用户(user)和权限(permission)之间没有直接的关系,都是通过角色作为代理,才能获取到用户(user)拥有的权限。
一个用户可以拥有若干角色,每一个角色有可以被分配若干权限这样,就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系,如下图
在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。
一般情况下,使用5张表就够了,3个实体表,2个关系表,设计如下所示:
casbin 上使用该模型
在 casbin 中使用 RBAC 模型需要在模型文件中添加 role_definition 模块:
[role_definition]
g = _, _
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
g = _,_
意味着在一个继承关系中有两个当事人,即定义了 用户——角色,角色——角色的映射关系,前者是后者的成员,拥有后者的权限。
然后在匹配器中,我们不需要判断 r.sub
与 p.sub
完全相等,只需要使用 g(r.sub, p.sub)
来判断请求主体 r.sub
是否属于 p.sub
这个角色即可。最后我们修改策略文件添加用户——角色定义:
p, admin, data, read
p, admin, data, write
p, developer, data, read
g, dajun, admin
g, lizi, developer
- dajun 属于 admin 管理员
- lizi 属于 developer 开发者,使用 g 来定义这层关系。
另外 admin 对数据 data 用 read 和 write 权限,而 developer 对数据 data 只有 read 权限。
package main
import (
"fmt"
"log"
"github.com/casbin/casbin/v2"
)
func check(e *casbin.Enforcer, sub, obj, act string) {
ok, _ := e.Enforce(sub, obj, act)
if ok {
fmt.Printf("%s CAN %s %s\n", sub, act, obj)
} else {
fmt.Printf("%s CANNOT %s %s\n", sub, act, obj)
}
}
func main() {
e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
if err != nil {
log.Fatalf("NewEnforecer failed:%v\n", err)
}
check(e, "dajun", "data", "read")
check(e, "dajun", "data", "write")
check(e, "lizi", "data", "read")
check(e, "lizi", "data", "write")
}